﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.WindowsAzure.ServiceRuntime;
using LoadGenerator;
using System.Collections;
using System.Web.UI.HtmlControls;
using System.Web.Script.Serialization;


namespace LoadController
{
    public partial class JobSetup : Page
    {
        private static Job job;
        
        protected void Page_Load(object sender, EventArgs e)
        {
            if (PreviousPage != null)
            {
                job = PreviousPage.job;
            }

            if (!Page.IsPostBack)
            {
                if (job != null)
                {
                    GeneratorConfigurations configurations = new GeneratorConfigurations();

                    foreach (var instance in RoleEnvironment.Roles["LoadGenerator"].Instances)
                    {
                        configurations.Add(new GeneratorConfigurations.GeneratorConfiguration());
                    }

                    repeater1.DataSource = configurations;
                    repeater1.DataBind();

                    FillDropDownList();
                }
                else
                {
                    Response.Redirect("~/Soap.aspx");
                }
            }
        }

        private void FillDropDownList()
        {
            ArrayList hours = new ArrayList();
            hours.Add(1);
            for (int i = 5; i <= 60; i+=5)
            {
                hours.Add(i);
            }

            DurationDropDownList.DataSource = hours;
            DurationDropDownList.DataBind();
        }


        private GeneratorConfigurations.GeneratorConfiguration GetConfigFromRepeaterItem(RepeaterItem item)
        {
            GeneratorConfigurations.GeneratorConfiguration gc = new GeneratorConfigurations.GeneratorConfiguration();
            gc.InstanceName = ((Label)item.FindControl("lblInstanceName")).Text;
            gc.StartUpDelay = int.Parse(((TextBox)item.FindControl("txtStartUpDelay")).Text);
            gc.NumberOfThreads = int.Parse(((TextBox)item.FindControl("txtNumberOfThreads")).Text);
            gc.ThreadStartUpDelay = int.Parse(((TextBox)item.FindControl("txtThreadStartUpDelay")).Text);
            gc.Duration = int.Parse(DurationDropDownList.SelectedItem.Value);
            return gc;
        }

        protected void repeater1_PreRender(object sender, System.EventArgs e)
        {          
            if (repeater1.Items.Count == 1)
            {
                btnRemove.Enabled = false;
            }
            else
            {
                btnRemove.Enabled = true;
            
            }

            if (repeater1.Items.Count == 10)
            {
                btnAdd.Enabled = false;
            }
            else
            {
                btnAdd.Enabled = true;
            }
        }


        protected void QueueJob_Click(object sender, EventArgs e)
        {
            ValidateRepeaterItems();
            
            if (Page.IsValid)
            {
                GeneratorConfigurations jobConfigs = new GeneratorConfigurations();

                foreach (RepeaterItem item in repeater1.Items)
                {
                    jobConfigs.Add(GetConfigFromRepeaterItem(item));
                }


                job.PartitionKey = "Job_" + (long.MaxValue - DateTime.UtcNow.Ticks).ToString();
                job.RowKey = JobNameTextBox.Text;
                job.InstanceCount = jobConfigs.Count;
                job.LoadConfigurations = jobConfigs.Serialize();
                job.Duration = int.Parse(DurationDropDownList.SelectedItem.Value);
                job.QueuedDateTime = DateTime.Now.ToString("G");

                AzureTableHelper.GetCloudTable(AppSettings.Table_Queue).Execute(TableOperation.Insert(job));

                Response.Redirect("~/Overview.aspx");
            }
        }


        private void ValidateRepeaterItems()
        {
            foreach (RepeaterItem item in repeater1.Items)
            {
                var instanceName = ((Label)item.FindControl("lblInstanceName")).Text;
                int Duration = int.Parse(this.DurationDropDownList.SelectedValue);

                bool StartUpDelayIsInteger = false;
                bool NumberOfThreadsIsIntegerAndInRange = false;
                bool ThreadStartUpDelayIsInteger = false;

                var StartUpDelay = ((TextBox)item.FindControl("txtStartUpDelay")).Text;
                if (!IsInteger(StartUpDelay))
                {
                    AddErrorToPage(instanceName, "StartUpDelay must be an integer");
                }
                else if (int.Parse(StartUpDelay) >= Duration)
                {
                    AddErrorToPage(instanceName, "StartUpDelay must be lower than Duration");
                }
                else
                {
                    StartUpDelayIsInteger = true;
                }

                var NumberOfThreads = ((TextBox)item.FindControl("txtNumberOfThreads")).Text;

                if (!IsInteger(NumberOfThreads))
                {
                    AddErrorToPage(instanceName, "Threads must be an integer");
                }
                else if (int.Parse(NumberOfThreads) > 100 || int.Parse(NumberOfThreads) < 1)
                {
                    AddErrorToPage(instanceName, "Threads Range (1-100)");
                }
                else
                {
                    NumberOfThreadsIsIntegerAndInRange = true;
                }

                var ThreadStartUpDelay = ((TextBox)item.FindControl("txtThreadStartUpDelay")).Text;
                if (!IsInteger(ThreadStartUpDelay))
                {
                    AddErrorToPage(instanceName, "ThreadStartUpDelay must be an integer");
                }
                else
                {
                    ThreadStartUpDelayIsInteger = true;
                }

                //Proof Logic
                if (StartUpDelayIsInteger && NumberOfThreadsIsIntegerAndInRange && ThreadStartUpDelayIsInteger)
                {
                    int startUpDelSecs = int.Parse(StartUpDelay)*60;
                    int threads = int.Parse(NumberOfThreads);
                    int threadStartUp = int.Parse(ThreadStartUpDelay);

                    int durationSecs = Duration * 60;                    
                    var threadProduct = threads * threadStartUp;

                    if ((startUpDelSecs + threadProduct) >= durationSecs)
                    {
                        if (threads > 1)
                        {
                            AddErrorToPage(instanceName, "Duration > (StartUpDelay + Threads * ThreadStartUpDelay) is not fulfilled");
                        }            
                    }
                }               
            }           
        }

        private void AddErrorToPage(string instName,string errMessage)
        {
            var err = new CustomValidator();
            err.ValidationGroup = "MyGroup";
            err.IsValid = false;
            err.ErrorMessage = instName +": "+ errMessage;
            Page.Validators.Add(err); 
        }

        private bool IsInteger(string x)
        {
            int value;
            return int.TryParse(x, out value);
        }


        protected void btnAdd_Click(object sender, EventArgs e)
        {
            ValidateRepeaterItems();
            if (Page.IsValid)
            {
                RepeaterItemCommand("Add"); 
            }
            
        }

        protected void btnRemove_Click(object sender, EventArgs e)
        {
            ValidateRepeaterItems();
            if (Page.IsValid)
            {
                RepeaterItemCommand("Remove");
            }    
        }

        private void RepeaterItemCommand(string CommandName)
        {
            if (CommandName == "Add" | CommandName == "Remove")
            {
                GeneratorConfigurations configurations = new GeneratorConfigurations();

                foreach (RepeaterItem item in repeater1.Items)
                {
                    if (!(CommandName == "Remove" && item.ItemIndex == repeater1.Items.Count - 1 && repeater1.Items.Count > 1))
                    {
                        configurations.Add(GetConfigFromRepeaterItem(item));
                    }
                }

                if (CommandName == "Add")
                {
                    configurations.Add(new GeneratorConfigurations.GeneratorConfiguration());
                }

                repeater1.DataSource = configurations;
                repeater1.DataBind();
            }
        }


        
    }     
    
}
